package reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * java反射机制
 * 反射是java的动态机制，可以在【程序运行期间】再确定如:对象实例化，方法调用，属性操作等
 * 反射可以提高代码的灵活性，可扩展性，但是带来了较多的系统开销和较慢的运行效率
 * 因此反射机制不能被过度依赖
 *
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
            反射的第一步是获取一个类的类对象
            java.lang.Class类，它的每一个实例被称为一个类的类对象
            JVM每当需要使用一个类时就会加载它的.class文件(字节码文件)并同时实例化一个
            Class实例来记录加载的类的相关信息，并且每个被加载的类都有且只有一个Class的
            实例与之绑定，这个Class的实例就可以理解为是刚加载的类的类对象。
            通过类对象可以反映出其表示的类的一切信息(类名，包信息，构造器信息，方法信息，属性信息)
            从而在程序运行期间进行动态调用

            获取一个类的类对象方式:
            1:类名.class
            2:对象.getClass()
            3:Class.forName()
            4:类加载器ClassLoader
         */
        //获取String的类对象
//        Class cls = String.class;
//        Class cls = ArrayList.class;


        /*
            Class.forName(String className)获取类对象
            此时该方法要求传入一个字符串，表示对应类的完全限定名
         */
//        Class cls = Class.forName("java.lang.String");
//        Class cls = Class.forName("java.util.ArrayList");

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个类名：");
        String cName = scanner.nextLine();
        Class cls = Class.forName(cName);



        //通过类对象反应出该类的名字
        String className = cls.getName();//获取完全限定名(包名.类名)
        System.out.println(className);
        className = cls.getSimpleName();//仅获取类名
        System.out.println(className);

        /*
            获取包信息
            Class提供的方法:
            Package getPackage()
            获取其表示的里的包信息。返回值为一个Package实例，该实例用于表示该包的信息

            Package是反射对象之一，与Class类似，只不过它的每一个实例仅反应一个包的相关内容
         */
        Package pack = cls.getPackage();
        String packName = pack.getName();//获取包名
        System.out.println("包名:"+packName);
        /*
            通过类对象反应它表示的类中所有的【公开方法】
            Method[] getMethods()

            java.lang.reflect.Method 类 ，反射对象之一
            它的每一个实例用于反应一个方法的相关信息
            通过Method对象得知其表示的类的:方法名，参数列表，返回值类型，访问修饰符等
         */
        Method[] methods = cls.getMethods();
        for(Method method : methods){
            String methodName = method.getName();
            System.out.println(methodName);
        }


    }
}


